<script setup lang="ts">
import { useRequest } from "ahooks-vue";
import { ArrayTable } from "@formily/element-plus";
import type { Field } from "@formily/core";
import { createForm, isField, onFieldInit, onFormInit } from "@formily/core";
import { ElMessage } from "element-plus";
import { ref } from "vue";
import { cloneDeep } from "lodash-es";
import { useRoute } from "vue-router";
import {
  StudentScore,
  baseInfoSchema,
  extraInfoSchema,
  schoolInfoSchema,
  scoreInfoSchema,
} from "@/views/student/schema";
import SchemaForm from "@/components/SchemaForm";
import {
  addStudentEducationInfo,
  addStudentFamilyInfo,
  deleteStudentEducationInfo,
  deleteStudentFamilyInfo,
  getSchoolDictInfo,
  getStudent,
  getStudentEducationInfo,
  getStudentFamilyInfo,
  getStudentScore,
  updateStudent,
  updateStudentEducationInfo,
  updateStudentFamilyInfo,
  updateStudentScore,
} from "@/api/student";
import type {
  Dept,
  Student,
  StudentEducationInfo,
  StudentFamilyInfo,
  StudentScoreInfo,
} from "@/types/user";
import useUserStore from "@/store/modules/user";
import useAddress from "@/hooks/useAddress";
import useDictFieldInit from "@/hooks/useDictFieldInit";
import { hasPermissions } from "@/directive/permission/hasPermi";

const userStore = useUserStore();
const route = useRoute();
const initValue: {
  familyMembers?: StudentFamilyInfo[];
  educationalExperience?: StudentEducationInfo[];
} = {};

const queryId = (route.params.Id as string) || userStore.name;

// 查询
async function query() {
  const [
    { data: studentInfo = {} as Student },
    { data: scoreInfo = {} },
    { rows: familyMembers = [] },
    { rows: educationalExperience = [] },
  ] = await Promise.all([
    getStudent(queryId),
    getStudentScore(queryId),
    getStudentFamilyInfo(queryId),
    getStudentEducationInfo(queryId),
  ]);

  // // 打印获取到的所有字段
  // console.log('学生基本信息字段：', Object.keys(studentInfo))
  // console.log('学生成绩信息字段：', Object.keys(scoreInfo))
  // console.log('家庭成员信息字段：', familyMembers.length > 0 ? Object.keys(familyMembers[0]) : [])
  // console.log('教育经历信息字段：', educationalExperience.length > 0 ? Object.keys(educationalExperience[0]) : [])
  //
  // // 打印完整的数据
  // console.log('学生基本信息：', studentInfo)
  // console.log('学生成绩信息：', scoreInfo)
  // console.log('家庭成员信息：', familyMembers)
  // console.log('教育经历信息：', educationalExperience)

  initValue.familyMembers = cloneDeep(familyMembers);
  initValue.educationalExperience = cloneDeep(educationalExperience);
  return {
    studentInfo,
    scoreInfo,
    familyMembers,
    educationalExperience,
  };
}

// 更新
async function update(
  values: Partial<
    Student &
      StudentScoreInfo & {
        familyMembers?: StudentFamilyInfo[];
        educationalExperience?: StudentEducationInfo[];
      }
  >,
  initValue: {
    familyMembers?: StudentFamilyInfo[];
    educationalExperience?: StudentEducationInfo[];
  }
) {
  const {
    familyMembers: initFamilyMembers = [],
    educationalExperience: initEducationalExperience = [],
  } = initValue;
  // 抽离学生分数数据
  const scoreInfo = Object.keys(StudentScore()).reduce(
    (previousValue, currentValue) => ({
      ...previousValue,
      [currentValue]: (values as Record<string, any>)[currentValue],
    }),
    { idCard: values.studentIdCard }
  );

  // 计算删除的学生家庭成员信息
  const familyRemove = initFamilyMembers
    .filter(
      (i) => (values.familyMembers || []).findIndex((j) => j.id === i.id) === -1
    )
    .map((i) => i.id)
    .join(",");
  // 计算删除的学生教育经历信息
  const educationRemove = initEducationalExperience
    .filter(
      (i) =>
        (values.educationalExperience || []).findIndex((j) => j.id === i.id) ===
        -1
    )
    .map((i) => i.id)
    .join(",");

  await Promise.all([
    // 更新学生信息 --- 此处提交了所有数据，可优化
    updateStudent(values as Student),
    // 更新学生分数信息
    updateStudentScore(scoreInfo as StudentScoreInfo),
    // 删除学生家庭成员信息
    familyRemove && deleteStudentFamilyInfo(familyRemove),
    // 删除的学生教育经历信息
    educationRemove && deleteStudentEducationInfo(educationRemove),
    // 根据是否有id判断是更新还是添加学生家庭成员信息
    ...(values.familyMembers?.map((row) =>
      row.id ? updateStudentFamilyInfo(row) : addStudentFamilyInfo(row)
    ) || []),
    // 根据是否有id判断是更新还是添加学生教育经历信息
    ...(values.educationalExperience?.map((row) =>
      row.id ? updateStudentEducationInfo(row) : addStudentEducationInfo(row)
    ) || []),
  ]);
}

const { run: doQuery, loading: infoLoading } = useRequest(query, {
  manual: true,
});
const { run: doUpdate, loading } = useRequest(update, {
  manual: true,
  throttleInterval: 500,
});

const transformerDept = (data: Dept[]) =>
  data.map((item) => ({
    label: item.deptName,
    value: item.deptName,
    id: item.deptId,
  }));

async function querySchoolDictByPre(
  field: Field,
  dataSource?: { label: string; value: string; id: number }[],
  value?: string
) {
  const pre = dataSource?.find((item) => item.value === value);
  if (pre) {
    field.loading = true;
    const { data } = await getSchoolDictInfo(pre.id);
    field.dataSource = transformerDept(data);
    if (field.dataSource.findIndex((item) => item.value === field.value) === -1)
      field.value = null;
    field.loading = false;
  }
}

const editable = ref(false);

const form = createForm<
  Partial<
    Student &
      StudentScoreInfo & {
        familyMembers?: StudentFamilyInfo[];
        educationalExperience?: StudentEducationInfo[];
      }
  >
>({
  initialValues: {},
  editable: editable.value,
  effects: () => {
    onFormInit(async (form1) => {
      const { studentInfo, scoreInfo, familyMembers, educationalExperience } =
        (await doQuery())!;
      form1.setValues(
        {
          ...studentInfo,
          ...scoreInfo,
          familyMembers,
          educationalExperience,
        },
        "overwrite"
      );
    });

    onFormInit((form) => {
      useAddress().then((res) => {
        if (res) {
          form.setFieldState("layout.province", (state) => {
            state.loading = true;
            state.dataSource = res.map((i) => ({
              label: i.label,
              value: i.value,
            }));
            state.loading = false;
          });
        }
      });
    });
    onFormInit((form) => {
      if (hasPermissions(["student:id:edit"])) {
        form.setFieldState("layout.studentCode", (state) => {
          state.disabled = false;
        });
      }
    });
    onFieldInit("layout.studentCollege", async (field) => {
      if (isField(field)) {
        field.loading = true;
        const { data } = await getSchoolDictInfo(-1);
        field.dataSource = transformerDept(data);
        field.loading = false;
      }
    });
    useDictFieldInit("layout.sex", "sys_user_sex");
    useDictFieldInit("layout.heath", "student_health_status");
    useDictFieldInit("layout.studentNation", "student_nation");
    useDictFieldInit("layout.studentPolitical", "student_political");
    useDictFieldInit("layout.admissionMethod", "student_admission_method");
    useDictFieldInit("layout.graduationType", "student_graduation_type");
    useDictFieldInit("layout.disciplines", "student_disciplines");
    useDictFieldInit("layout.foreignLanguage", "student_language");
    useDictFieldInit("layout.familyMembers.*.nation", "student_nation");
    useDictFieldInit("layout.familyMembers.*.political", "student_political");
  },
});
async function handleSubmit() {
  try {
    await form.submit((values) => doUpdate(values, initValue));
    ElMessage({ message: "修改成功", type: "success" });
    const { studentInfo, scoreInfo, familyMembers, educationalExperience } =
      (await doQuery())!;
    form.setValues(
      {
        ...studentInfo,
        ...scoreInfo,
        familyMembers,
        educationalExperience,
      },
      "shallowMerge"
    );
  } catch (e) {
    ElMessage({
      message: "填写内容存在错误，请仔细检查填写内容",
      type: "error",
    });
  }
}

async function toggleEditable() {
  if (editable.value) {
    const { studentInfo, scoreInfo, familyMembers, educationalExperience } =
      (await doQuery())!;
    form.setValues(
      {
        ...studentInfo,
        ...scoreInfo,
        familyMembers,
        educationalExperience,
      },
      "overwrite"
    );
  }
  editable.value = !editable.value;
  form.setFormState((state) => {
    state.editable = editable.value;
  });
}
</script>

<template>
  <div class="w-full p-2 md:p-4 bg-[#F4F7F9]">
    <ElRow v-loading="infoLoading" class="pb-2 md:pb-4">
      <ElButton
        v-loading="loading"
        type="primary"
        :disabled="!editable"
        @click="handleSubmit"
      >
        保存
      </ElButton>
      <ElButton @click="toggleEditable">
        {{ editable ? "取消" : "修改" }}
      </ElButton>
    </ElRow>
    <ElRow v-loading="infoLoading" class="mb-4">
      <ElCol :span="24">
        <ElCard class="box-card">
          <template #header>
            <div class="clearfix">
              <span
                >学生基础信息（带星号的必填，必填项不知道怎么填就填"无"，不需要加双引号）</span
              >
            </div>
          </template>
          <div class="w-full">
            <SchemaForm :schema="baseInfoSchema" :form="form" />
          </div>
        </ElCard>
      </ElCol>
    </ElRow>
    <ElRow v-loading="infoLoading" class="mb-4">
      <ElCol :span="24">
        <ElCard class="box-card">
          <template #header>
            <div class="clearfix">
              <span>在校信息</span>
            </div>
          </template>
          <div class="w-full">
            <SchemaForm
              :schema="schoolInfoSchema"
              :form="form"
              :scope="{ querySchoolDictByPre }"
            />
          </div>
        </ElCard>
      </ElCol>
    </ElRow>
    <ElRow v-loading="infoLoading" class="mb-4">
      <ElCol :span="24">
        <ElCard class="box-card">
          <template #header>
            <div class="clearfix">
              <span>学生高考信息</span>
            </div>
          </template>
          <div class="w-full">
            <SchemaForm :schema="scoreInfoSchema" :form="form" />
          </div>
        </ElCard>
      </ElCol>
    </ElRow>
    <ElRow v-loading="infoLoading" class="mb-4">
      <ElCol :span="24">
        <ElCard class="box-card">
          <template #header>
            <div class="clearfix">
              <span>学生补充信息</span>
            </div>
          </template>
          <div class="w-full">
            <SchemaForm
              :schema="extraInfoSchema"
              :components="{ ArrayTable }"
              :form="form"
            />
          </div>
        </ElCard>
      </ElCol>
    </ElRow>
    <ElBacktop :right="100" :bottom="100" />
  </div>
</template>
